// Copyright (c) 2024, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

@OnPlatform({'mac-os': Timeout.factor(2), 'windows': Timeout.factor(10)})
// TODO(https://github.com/dart-lang/native/issues/190): Enable on windows once
// https://github.com/dart-lang/sdk/commit/903eea6bfb8ee405587f0866a1d1e92eea45d29e
// has landed in dev channel.
@TestOn('!windows')
library;

import 'dart:convert';
import 'dart:io';

import 'package:code_assets/code_assets.dart';
import 'package:hooks/hooks.dart';
import 'package:test/test.dart';

import '../helpers.dart';

void main() async {
  late Uri tempUri;
  const name = 'native_dynamic_linking';

  setUp(() async {
    tempUri = (await Directory.systemTemp.createTemp()).uri;
  });

  tearDown(() async {
    await Directory.fromUri(tempUri).delete(recursive: true);
  });

  test(
    'native_dynamic_linking build',
    skip:
        (Platform.isMacOS || Platform.isWindows) &&
            Platform.environment['GITHUB_ACTIONS'] != null
        ? 'https://github.com/dart-lang/native/issues/2501'
        : false,
    () async {
      final buildOutputUri = tempUri.resolve('build_output.json');
      final testTempUri = tempUri.resolve('test1/');
      await Directory.fromUri(testTempUri).create();
      final outputDirectory = tempUri.resolve('out/');
      await Directory.fromUri(outputDirectory).create();
      final outputDirectoryShared = tempUri.resolve('out_shared/');
      await Directory.fromUri(outputDirectoryShared).create();
      final testPackageUri = packageUri.resolve('example/build/$name/');
      final dartUri = Uri.file(Platform.resolvedExecutable);

      final targetOS = OS.current;
      final inputBuilder = BuildInputBuilder()
        ..setupShared(
          packageRoot: testPackageUri,
          packageName: name,
          outputFile: buildOutputUri,
          outputDirectoryShared: outputDirectoryShared,
        )
        ..config.setupBuild(linkingEnabled: false)
        ..addExtension(
          CodeAssetExtension(
            targetOS: targetOS,
            macOS: targetOS == OS.macOS
                ? MacOSCodeConfig(targetVersion: defaultMacOSVersion)
                : null,
            targetArchitecture: Architecture.current,
            linkModePreference: LinkModePreference.dynamic,
            cCompiler: cCompiler,
          ),
        );

      final buildInputUri = testTempUri.resolve('build_input.json');
      await File.fromUri(
        buildInputUri,
      ).writeAsString(jsonEncode(inputBuilder.json));

      final processResult = await Process.run(dartUri.toFilePath(), [
        'hook/build.dart',
        '--config=${buildInputUri.toFilePath()}',
      ], workingDirectory: testPackageUri.toFilePath());
      if (processResult.exitCode != 0) {
        print(processResult.stdout);
        print(processResult.stderr);
        print(processResult.exitCode);
      }
      expect(processResult.exitCode, 0);

      final buildOutput = BuildOutput(
        json.decode(await File.fromUri(buildOutputUri).readAsString())
            as Map<String, Object?>,
      );
      final assets = buildOutput.assets.encodedAssets;
      final dependencies = buildOutput.dependencies;

      expect(assets.length, 3);
      expect(await assets.allExist(), true);
      expect(dependencies, [
        testPackageUri.resolve('src/debug.c'),
        testPackageUri.resolve('src/math.c'),
        testPackageUri.resolve('src/add.c'),
      ]);
    },
  );
}
